import React, {
  FC,
  ReactElement,
  useCallback,
  useEffect,
  useReducer
} from 'react';
import { ACTION_TYPE, IState, ITodo } from '../../typings';

import TdInput from './Input';
import TdList from './List';
import { todoReducer } from './reducer';

const TodoList: FC = (): ReactElement => {
  /**
   * 问题：`useReducer`有什么存在意义？
   *   它比`useState`的写法更为高级，也是一个更高级的解决方案，当使用多个方法操作一个状态数据的变化时，而且这些方法内部有相对比较复杂的逻辑时，可以用`useReducer`来处理
   *   并且，使用`useReducer`还能给那些触发更新的组件做性能优化，因为开发者项子组件传递的是`dispatch`而不是回调函数
   */

  /**
 * 写法1：useState
 *   //初始化一个数组
  const [todoList, setTodoList] = useState<ITodo[]>([]);

  //监听todoList数据变化
  useEffect(() => {
    console.log(todoList);
  }, [todoList]);

  //性能优化
  const addTodo = useCallback((todo: ITodo): void => {
    //展开数组并放入新的项
    setTodoList((todoList) => [...todoList, todo]);
  }, []);
 */

  /**
   * 写法2：useReducer
   */
  //声明一个初始state对象
  // const initialState: IState = {
  //   todoList: []
  // };

  //对state数据进行惰性初始化处理
  function init(initTodoList: ITodo[]): IState {
    return {
      todoList: initTodoList
    };
  }

  //使用useReducer
  //正常写法
  // const [state, dispatch] = useReducer(todoReducer, initialState);
  //惰性初始化写法 此写法在useReducer执行时才创建init函数里面的对象
  const [state, dispatch] = useReducer(todoReducer, [], init);

  //首次加载
  useEffect(() => {
    // console.log(state.todoList);
    //localStorage存取
    const todoList = JSON.parse(localStorage.getItem('todoList') || '[]');

    //将localStorage拿到的todoList赋值给state状态里的todoList
    dispatch({
      type: ACTION_TYPE.INIT_TODOLIST,
      payload: todoList
    });
  }, []);

  //每次操作导致state.todoList数据发生变更时重新执行
  useEffect(() => {
    //保存操作后的state.todoList到localStorage
    localStorage.setItem('todoList', JSON.stringify(state.todoList));
  }, [state.todoList]);

  //点击新增按钮 新增一项
  const addTodo = useCallback((todo: ITodo): void => {
    //使用useReducer里dispatch 新增一项todo
    dispatch({
      type: ACTION_TYPE.ADD_TODO,
      payload: todo
    });
  }, []);

  //删除某一项
  const removeTodo = useCallback((id: number): void => {
    dispatch({
      type: ACTION_TYPE.REMOVE_TODO,
      payload: id
    });
  }, []);

  //修改某一项里内容
  const toggleTodo = useCallback((id: number): void => {
    dispatch({
      type: ACTION_TYPE.TOGGLE_TODO,
      payload: id
    });
  }, []);

  return (
    <div className="todo-list">
      <TdInput addTodo={addTodo} todoList={state.todoList} />
      <TdList
        todoList={state.todoList}
        removeTodo={removeTodo}
        toggleTodo={toggleTodo}
      />
    </div>
  );
};

export default TodoList;
